package serv

import (
	"fmt"
	"log"
	"net"
	"netfly/comm"
	"strings"

	"github.com/tidwall/gjson"
)

var (
	CtrlClientList []comm.ClientConf
	ctrlServBuff   []byte
)

func RunCtrlServer(strAddr string) {
	log.Println("Listen CtrlServer", strAddr)
	sListen, err := net.Listen("tcp", strAddr)
	if err != nil {
		log.Println("Listen", strAddr, "Error:", err.Error())
		return
	}
	if CtrlClientList == nil {
		CtrlClientList = make([]comm.ClientConf, 0)
	}
	if ctrlServBuff == nil {
		ctrlServBuff = make([]byte, 0)
	}

	for {
		c, err := sListen.Accept()
		if err != nil {
			continue
		}
		cConf := comm.ClientConf{
			CtrlConn: c,
			PortServ: make(map[string]*net.Listener, 0),
		}
		CtrlClientList = append(CtrlClientList, cConf)
		log.Println(CtrlClientList)
		go HandleCtrlConn(&cConf)
	}
}

func HandleCtrlConn(cConf *comm.ClientConf) {
	tmpBuff := make([]byte, 2048)
	for {
		n, err := cConf.CtrlConn.Read(tmpBuff)
		if err != nil {
			log.Println("Client", cConf.Token, "Error!")
			HandleClientError(cConf)
			break
		}
		ctrlServBuff = append(ctrlServBuff, tmpBuff[:n]...)
		for {
			oneMsgBin, ok := comm.UnPackMsg(&ctrlServBuff)
			if ok == false {
				break
			}
			HandleMsg(string(oneMsgBin), cConf)
		}
	}

	cConf.CtrlConn.Close()
}

func HandleClientError(c *comm.ClientConf) {
	for k, v := range c.PortServ {
		(*v).Close()
		log.Println("Close Client Port Server:", k)
	}
	// clear
	c.PortServ = make(map[string]*net.Listener)
}
func HandleMsg(msg string, c *comm.ClientConf) {
	if len(msg) < 1 {
		return
	}
	strToken := gjson.Get(msg, "token").String()
	strAsk := gjson.Get(msg, "ask").String()
	log.Println("Ctrl Msg", msg, strAsk)
	if strAsk == "login" {
		strRet := "failed"
		c.Token = ""
		// token check
		if strings.Contains(strToken, "abc") {
			c.Token = strToken
			strRet = "ok"
		}
		sMsg := fmt.Sprintf(`{"token":"%v","answer":"%v"}`, strToken, strRet)
		comm.SendCtrlMsg(sMsg, c.CtrlConn)
		if strRet != "ok" {
			// close it
			c.CtrlConn.Close()
		}
	}
	if strAsk == "open" {
		log.Println(c.Token, strToken)
		if c.Token == strToken {
			cPort := gjson.Get(msg, "port").String()
			sMsg := fmt.Sprintf(`{"token":"%v","port":"%v","answer":"ok"}`, strToken, cPort)
			comm.SendCtrlMsg(sMsg, c.CtrlConn)
			go RunPortServer(":"+cPort, c)

		}
	}
}
